﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Drifting.Foundation;

namespace Drifting.Graphics.EffectObjects
{
    public class Box : EffectObject
    {
        static short[] quad_Indices;
        private VertexPositionColor[] vertices;
        private BasicEffect effects;
        private Matrix configuration;

        private VertexPositionNormalTexture[] vtexture;
        private short[] v_indices;

        public double[] Config
        {
            set {
                float x = (float)value[0];
                float y = (float)value[1];
                float z = (float)value[2];
                float rx = (float)value[3];
                float ry = (float)value[4];
                float rz = (float)value[5];

                float angle = (float)Math.Sqrt(rx * rx + ry * ry + rz * rz);
                if (angle != 0)
                {
                    rx /= angle;
                    ry /= angle;
                    rz /= angle;
                }
                configuration = Matrix.CreateFromAxisAngle(new Vector3(rx, ry, rz), angle) * Matrix.CreateTranslation(x, y, z);
                
            }
        }

        public Box(double length, double width, double height, Color color, GraphicsDevice device)
            : base(device)
        {
            float lh = (float)(length / 2);
            float wh = (float)(width / 2);
            float hh = (float)(height / 2);

            vertices = new VertexPositionColor[8];
            vertices[0] = new VertexPositionColor(new Vector3(-lh, -hh, -wh), color);
            vertices[1] = new VertexPositionColor(new Vector3(-lh, -hh, wh), color);
            vertices[2] = new VertexPositionColor(new Vector3(-lh, hh, wh), color);
            vertices[3] = new VertexPositionColor(new Vector3(-lh, hh, -wh), color);
            vertices[4] = new VertexPositionColor(new Vector3(lh, hh, -wh), color);
            vertices[5] = new VertexPositionColor(new Vector3(lh, hh, wh), color);
            vertices[6] = new VertexPositionColor(new Vector3(lh, -hh, wh), color);
            vertices[7] = new VertexPositionColor(new Vector3(lh, -hh, -wh), color);


            /////////// normal vertex /////////////
            Vector3 v_front = new Vector3(1,0,0);
            Vector3 v_back = new Vector3(-1,0,0);

            Vector3 p_front_1 = new Vector3(lh, hh, wh);
            Vector3 p_front_2 = new Vector3(lh, -hh, wh);
            Vector3 p_front_3 = new Vector3(lh, -hh, -wh);
            Vector3 p_front_4 = new Vector3(lh, hh, -wh);

            vtexture = new VertexPositionNormalTexture[8];
            vtexture[0] = new VertexPositionNormalTexture(p_front_1, v_front,new Vector2(0,0));
            vtexture[1] = new VertexPositionNormalTexture(p_front_2, v_front, new Vector2(1, 0));
            vtexture[2] = new VertexPositionNormalTexture(p_front_3, v_front, new Vector2(1, 1));
            vtexture[3] = new VertexPositionNormalTexture(p_front_4, v_front, new Vector2(0, 1));

            v_indices = new short[6];
            v_indices = new short[] {   0,1,2,
                                        2,3,0};
            //////////////////////////////////////////////////////



            if (quad_Indices == null)
            {
                quad_Indices = new short[] { 0, 1, 2, 
                                             2, 3, 0,
                                             2, 3, 4,
                                             2, 4, 5,
                                             4, 7, 5,
                                             5, 7, 6,
                                             7, 6, 1,
                                             7, 1, 0,
                                             1, 2, 5,
                                             5, 6, 1,
                                             3, 4, 7,
                                             3, 7, 0};
                
            }
            effects = new BasicEffect(device);

            configuration = Matrix.Identity;
        }

        public void SetConfig(Matrix m)
        {
            configuration = m;
        }


        public void Draw(Matrix view, Matrix projection, float[] f33)
        {
            float d1 = f33[3] - f33[0];
            float d2 = f33[4] - f33[1];
            float d3 = f33[5] - f33[2];
            Vector3 v_delta = new Vector3(d1, d2, d3);
            Vector3 v_position = new Vector3(f33[0], f33[1], f33[2]);
            Draw(view, projection, v_position, v_delta);
        }

        public void Draw(Matrix view, Matrix projection, Vector3 v_position, Vector3 v_delta)
        {
            Vector3 v_original = new Vector3(1, 0, 0);
            float v_delta_length = v_delta.Length();

            Vector3 axis = MathAssistant.vector_cross3(v_original, v_delta);
            float sinT = axis.Length() / v_delta_length;
            axis.Normalize();
            float cosT = (float)MathAssistant.vector_dotProduct(v_original, v_delta) / v_delta_length;
            float T = MathAssistant.AngleFromSinCos(sinT, cosT);

            Matrix config = 
                Matrix.CreateScale(v_delta_length, 1, 1) *
                Matrix.CreateTranslation(v_delta_length / 2, 0, 0) * 
                Matrix.CreateFromAxisAngle(axis, T) * 
                Matrix.CreateTranslation(v_position);

            Draw(view, projection, config);
        }

        override public void Draw(Matrix view, Matrix projection)
        {
            effects.VertexColorEnabled = true;
            effects.World = configuration;
            effects.View = view;
            effects.Projection = projection;

            effects.CurrentTechnique.Passes[0].Apply();
            device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, 8, quad_Indices, 0, 12);
        }
        
        public void Draw(Matrix view, Matrix projection, Matrix config)
        {
            effects.VertexColorEnabled = true;
            effects.World = config;
            effects.View = view;
            effects.Projection = projection;

            effects.CurrentTechnique.Passes[0].Apply();
            device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, 8, quad_Indices, 0, 12);
        }

    }
}
